package com.renfei.ffmpegvideoplayer;

import android.media.MediaCodec;
import android.media.MediaFormat;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;
import android.view.Surface;

import androidx.annotation.RequiresApi;

import com.renfei.ffmpegvideoplayer.listener.OnPlayerCompleteListener;
import com.renfei.ffmpegvideoplayer.listener.OnPlayerErrorListener;
import com.renfei.ffmpegvideoplayer.listener.OnPlayerLoadListener;
import com.renfei.ffmpegvideoplayer.listener.OnPlayerParparedListener;
import com.renfei.ffmpegvideoplayer.listener.OnPlayerStatusChangeListener;
import com.renfei.ffmpegvideoplayer.listener.OnVideoPlayInfoListener;
import com.renfei.ffmpegvideoplayer.listener.OnYuvDataCallBackListener;
import com.renfei.ffmpegvideoplayer.util.MuteEnum;
import com.renfei.ffmpegvideoplayer.util.VideoSupportUtil;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.nio.ByteBuffer;

public class FFmpegPlayer {
    private static final String TAG = "FFmpegPlayer";

    static {
        System.loadLibrary("native-lib");
    }


    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
    public native String stringFromJNI();


    private OnYuvDataCallBackListener onYuvDataCallBackListener;
    private OnPlayerParparedListener onPlayerParparedListener;
    private OnPlayerLoadListener onPlayerLoadListener;
    private OnPlayerErrorListener onPlayerErrorListener;
    private OnPlayerCompleteListener onPlayerCompleteListener;
    private OnPlayerStatusChangeListener onPlayerStatusChangeListener;
    private OnVideoPlayInfoListener onVideoPlayInfoListener;

    private String videoSource;
    private VideoPlayGlSurfaceView glSurfaceView;
    private int currentVolume = 50;
    private MuteEnum currentMute = MuteEnum.MUTE_CENTER;
    private VideoTimeInfo videoTimeInfo = null;
    private int duration = -1;
    /**
     * mediaCodec 是否初始化
     */
    private boolean isMediaCodecInitSuccess = false;

    /**
     * 硬解码
     */
    private MediaFormat mediaFormat;
    private MediaCodec mediaCodec;
    private Surface surface;
    private MediaCodec.BufferInfo bufferInfo;

    public void setSource(String targetSource) {
        this.videoSource = targetSource;
    }

    public void parpared() {
        if (TextUtils.isEmpty(videoSource)) {
            Log.e(TAG, "videoSource is null");
            return;
        }
        OnLoad(true);//开始加载

//        n_parpared(videoSource);
        new Thread() {
            @Override
            public void run() {
                super.run();
                n_parpared(videoSource);
            }
        }.start();

    }

    public void startPlay() {
        new Thread() {
            @Override
            public void run() {
                super.run();
                setVolume(currentVolume);
                setMute(currentMute);
                n_start();
            }
        }.start();
    }

    public void pause() {
        n_pause();
        if (null != onPlayerStatusChangeListener) {
            onPlayerStatusChangeListener.onPause(true);
        }
    }

    public void resume() {
        n_resume();
        if (null != onPlayerStatusChangeListener) {
            onPlayerStatusChangeListener.onPause(false);
        }
    }

    public void stop() {
        videoTimeInfo = null;
        duration = 0;
        new Thread() {
            @Override
            public void run() {
                n_stop();
                releaseMediacodec();
            }
        }.start();
    }

    public void seek(int seekPosition) {
        n_seek(seekPosition);
    }

    public void setVolume(int percent) {
        currentVolume = percent;
        n_setVolume(currentVolume);
    }

    public void setMute(MuteEnum mute) {
        currentMute = mute;
        n_setmute(mute.getValue());
    }


    public int getVolume() {
        return currentVolume;
    }

    public int getDuration() {
        if (duration < 0) {
            return n_duration();
        }
        return duration;
    }

    private native void n_parpared(String source);

    private native void n_start();

    private native void n_pause();

    private native void n_resume();

    private native void n_stop();

    private native void n_seek(int seekPosition);

    private native int n_duration();

    private native void n_setVolume(int percent);

    private native void n_setmute(int mute);


    private void releaseMediacodec() {
        if (null != mediaCodec) {
            try {
                mediaCodec.flush();
                mediaCodec.stop();
                mediaCodec.release();
            }catch (Exception e){
                e.printStackTrace();
            }

            mediaCodec = null;
            mediaFormat = null;
            bufferInfo = null;
        }
    }

    /**
     * C++ 调用Java的方法 start
     */

    public void OnParpared() {
        if (null != onPlayerParparedListener) {
            onPlayerParparedListener.onParpared();
        }
    }

    public void OnLoad(boolean load) {
        if (null != onPlayerLoadListener) {
            onPlayerLoadListener.onLoad(load);
        }
    }

    public void OnError(int code, String msg) {
        if (null != onPlayerErrorListener) {
            onPlayerErrorListener.onError(code, msg);
        }
    }

    public void OnDecodecComplete() {
//        stop();
        if (null != onPlayerCompleteListener) {
            onPlayerCompleteListener.onComplete();
        }
    }

    public void onCallRenderYuv(int width, int height, byte[] y, byte[] u, byte[] v) {

        //   Log.e("onCallRenderYuv", "onCallRenderYuv width =" + width
        //           + "  height = " + height
        //           + "  y = " + y.length
        //           + "  u = " + u.length
        //           + "  v = " + v.length
        //   );


        if (null != glSurfaceView) {
            glSurfaceView.getYuvRender().setRenderType(YuvRender.RENDER_TYPE_YUV);
            glSurfaceView.setYuvRenderData(width, height, y, u, v);
        }
        //  if (null!=onYuvDataCallBackListener){
        //      onYuvDataCallBackListener.onYuvDataCallBack(width, height, y, u, v);
        //  }
    }

    /**
     * 播放时长
     *
     * @param currentTime
     * @param totalTime
     */
    public void onCallTimeInfo(int currentTime, int totalTime) {
//        Log.e(TAG, "currentTime is : "+currentTime +" totalTime is "+totalTime);

        if (null != onVideoPlayInfoListener) {
            if (null == videoTimeInfo) {
                videoTimeInfo = new VideoTimeInfo();
            }
            videoTimeInfo.setCurrentTime(currentTime);
            videoTimeInfo.setTotalTime(totalTime);
            onVideoPlayInfoListener.onVideoPlayInfo(videoTimeInfo);
        }
    }


    public boolean onCllIsSupportMediaCodec(String codecName) {
        return VideoSupportUtil.isLocalSupportCodec(codecName);
    }

    /**
     * 初始化  MediaCodec
     *
     * @param codecName
     * @param width
     * @param height
     * @param csd_0
     * @param csd_1
     */
    public void initMiediaCodec(String codecName, int width, int height, byte[] csd_0, byte[] csd_1) {
        Log.e(TAG, "initMiediaCodec: ");
        if (surface != null) {
            try {
                glSurfaceView.getYuvRender().setRenderType(
                        YuvRender.RENDER_TYPE_SURFACE
                );
                String mintType = VideoSupportUtil.findVideoCodecName(codecName);
                mediaFormat = MediaFormat.createVideoFormat(
                        mintType, width, height);

                mediaFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, width * height);
                mediaFormat.setByteBuffer("csd-0", ByteBuffer.wrap(csd_0));
                mediaFormat.setByteBuffer("csd-1", ByteBuffer.wrap(csd_1));
                Log.e(TAG, "mediaFormat: " + mediaFormat.toString());

                mediaCodec = MediaCodec.createDecoderByType(mintType);

                mediaCodec.configure(mediaFormat, surface, null, 0);

                mediaCodec.start();
                bufferInfo = new MediaCodec.BufferInfo();
                isMediaCodecInitSuccess = true;
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            if (onPlayerErrorListener == null) {
                onPlayerErrorListener.onError(2001, "surface is null");
            }
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public void decodecAvpacket(int size, byte[] data) {

        Log.e(TAG, "decodecAvpacket: size is " + size);

        if (isMediaCodecInitSuccess && null != surface) {
            if (size > 0 && null != data) {

                Log.e(TAG, "decodecAvpacket isMediaCodecInitSuccess: ");
                try {

                    int inputBufferIndex = mediaCodec.dequeueInputBuffer(1000);
                    Log.e(TAG, "inputBufferIndex: " + inputBufferIndex);
                    if (inputBufferIndex > 0) {
                        ByteBuffer byteBuffer = mediaCodec.getInputBuffer(inputBufferIndex);
                        byteBuffer.clear();
                        byteBuffer.put(data);
                        mediaCodec.queueInputBuffer(inputBufferIndex, 0, size, 0, 0);
                    }
                    int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 10000);
                    Log.e(TAG, "outputBufferIndex: " + outputBufferIndex);
                    while (outputBufferIndex >= 0) {
                        Log.e(TAG, "outputBufferIndex 大于等于0: " + outputBufferIndex);
                        mediaCodec.releaseOutputBuffer(outputBufferIndex, true);
                        outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 10000);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * C++ 调用Java的方法 end
     */


    public void setGlSurfaceView(VideoPlayGlSurfaceView glSurfaceView) {
        this.glSurfaceView = glSurfaceView;
        glSurfaceView.getYuvRender().setOnTextureCreateListener(new YuvRender.onTextureCreateListener() {
            @Override
            public void onCreate(Surface s) {
                if (surface == null) {
                    surface = s;
                }
            }
        });
    }

    /**
     * 监听器
     */


    public void setOnYuvDataCallBackListener(OnYuvDataCallBackListener onYuvDataCallBackListener) {
        this.onYuvDataCallBackListener = onYuvDataCallBackListener;
    }

    public void setOnPlayerParparedListener(OnPlayerParparedListener onPlayerParparedListener) {
        this.onPlayerParparedListener = onPlayerParparedListener;
    }

    public void setOnPlayerLoadListener(OnPlayerLoadListener onPlayerLoadListener) {
        this.onPlayerLoadListener = onPlayerLoadListener;
    }

    public void setOnPlayerErrorListener(OnPlayerErrorListener onPlayerErrorListener) {
        this.onPlayerErrorListener = onPlayerErrorListener;
    }

    public void setOnPlayerCompleteListener(OnPlayerCompleteListener onPlayerCompleteListener) {
        this.onPlayerCompleteListener = onPlayerCompleteListener;
    }

    public void setOnPlayerStatusChangeListener(OnPlayerStatusChangeListener onPlayerStatusChangeListener) {
        this.onPlayerStatusChangeListener = onPlayerStatusChangeListener;
    }

    public void setOnVideoPlayInfoListener(OnVideoPlayInfoListener onVideoPlayInfoListener) {
        this.onVideoPlayInfoListener = onVideoPlayInfoListener;
    }
}
